/**
 * @file TJCScreen.c
 * @brief 淘晶驰串口屏串口显示驱动文件
 * @author 2bam 
 * @version 1.0
 * @date 2024-12-16
 * @copyright Copyright (c) 2024  NULL
 * 
 * @change log:
 * Date           Version Author   Describe
 * 2024-12-16     1.0     2bam     first version
 */


/* Includes -------------------------------------------------------------------*/
#include "TJCScreen.h"
/* define ---------------------------------------------------------------------*/
#define TJC_SINGLE_MESSAGE_SIZE		128
#define TJC_UART_POINTER            huart2
#define TJC_TEXT_PAGE1  "serial2.t2.txt+=\""
/* typedef --------------------------------------------------------------------*/

/* variables ------------------------------------------------------------------*/
struct rt_messagequeue tjc_mq;
static rt_uint8_t tjc_msg_pool[2048];
struct rt_thread tjc_thread;
static uint8_t tjc_stack[2048];
/* Private function prototypes ------------------------------------------------*/


/**
 * @brief 直接打印到TJC串口屏的格式化函数，可以不通过线程执行
 * 此处为了使用DMA做了很多额外的工作，如果是轮询打印就完全无需
 * 增加这些内容。
 * @param  fmt         My Param doc
 * @param  ...         My Param doc
 * @date 2024-05-15
 * @author 2bam 
 */
void printf_tjc(const char *fmt, ...)
{
    va_list args;
    size_t length;
    static char buf[TJC_SINGLE_MESSAGE_SIZE];
    /** 先等待DMA为空闲，否则数据可能被迅速覆盖 2024-12-17 Tuesday 23:07:14*/
    while(__HAL_UART_GET_FLAG(&TJC_UART_POINTER, UART_FLAG_TC)==RESET);

    va_start(args, fmt);
    /* the return value of vsnprintf is the number of bytes that would be
     * written to buffer had if the size of the buffer been sufficiently
     * large excluding the terminating null byte. If the output string
     * would be larger than the rt_log_buf, we have to adjust the output
     * length. */
    length = vsnprintf(buf, sizeof(buf) - 1, fmt, args);
    if (length > TJC_SINGLE_MESSAGE_SIZE - 1)
        length = TJC_SINGLE_MESSAGE_SIZE - 1;
    va_end(args); 
    /** 打印到特定页面 2024-12-14 Saturday 00:25:58 */
	/** 将显示信息修改为追加模式：+= 2024-12-14 Saturday 10:44:40 */
    /** 使用DMA发送的数据内存段应该定义为静态 2024-12-17 Tuesday 21:03:46*/
    static char buff_send[TJC_SINGLE_MESSAGE_SIZE];
    /** 因为strcat的存在，这里需要先清除缓存 2024-12-17 Tuesday 22:40:10 */
    memset(buff_send,0,sizeof(buff_send));
    /** strcat将源字符串拼接到目标字符串上
     * 其与静态变量相互作用又会出问题，因此使用memset清除一下变量
     *  2024-12-17 Tuesday 22:42:01 */
    strcat(buff_send,TJC_TEXT_PAGE1);
	strcat(buff_send,buf);
    strcat(buff_send,"\"\xff\xff\xff");
    /* 使用USART2 DMA模式进行输出 2024/05/15 Wednesday 23:24:28 */  
    HAL_UART_Transmit_DMA(&TJC_UART_POINTER,(uint8_t *)buff_send,strlen(buff_send));
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)buff_send,strlen(buff_send));
}


/**
 * @brief 
 * @param  des         My Param doc
 * @param  str         My Param doc
 * @param  size        My Param doc
 * @date 2024-12-14
 * @author 2bam 
 */
void log_tjc(const char *fmt, ...)
{
    va_list args;
    size_t length;
    static char buf[TJC_SINGLE_MESSAGE_SIZE];

    va_start(args, fmt);
    length = vsnprintf(buf, sizeof(buf) - 1, fmt, args);
    if (length > TJC_SINGLE_MESSAGE_SIZE - 1)
        length = TJC_SINGLE_MESSAGE_SIZE - 1;

    /** 将消息内容添加到队列中进行排队输出 2024-12-17 Tuesday 21:38:31 */
	rt_mq_send(&tjc_mq,buf,length);
    va_end(args); 
}




/**
 * @brief 
 * @param  para        My Param doc
 * @date 2024-12-16
 * @author 2bam 
 */
static void TJCTextDisplayEntry(void *para)
{
    static char buf[TJC_SINGLE_MESSAGE_SIZE];

    while (1)
    {
        if (rt_mq_recv(&tjc_mq, &buf, sizeof(buf), RT_WAITING_FOREVER) == RT_EOK)
        {
            /** 输出到串口屏 */
            printf_tjc("%s",buf);
        }
        rt_thread_mdelay(5);
    }
}


/**
 * @brief 创建文本显示线程
 * @return int 
 * @date 2024-12-16
 * @author 2bam 
 */
int TJCScreenResourceInit(void)
{
    rt_err_t ret;

    //printf_tjc("hello\\\"world\\\"");
    printf_tjc("MIT License\r\n");
    printf_tjc("\r\nCopyright (c) 2024 Snibe Team\r\n");
    printf_tjc("\r\nPermission is hereby granted, free of charge, to any person obtaining a copy");
    printf_tjc(" of this software and associated documentation files (the \\\"Software\\\"), to deal in");
    printf_tjc(" the Software without restriction, including without limitation the rights");
    printf_tjc(" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell");
    printf_tjc(" copies of the Software, and to permit persons to whom the Software is");
    printf_tjc(" furnished to do so, subject to the following conditions.\r\n");



    ret = rt_mq_init(&tjc_mq,
                        "tjc msg queue",
                        &tjc_msg_pool[0],             
                        TJC_SINGLE_MESSAGE_SIZE,                        
                        sizeof(tjc_msg_pool),        
                        RT_IPC_FLAG_FIFO);       
    if (ret != RT_EOK)
    {
        rt_kprintf("init TJC message queue failed.\n");
        return -1;
    }

    ret = rt_thread_init(&tjc_thread,
                        "tjc thread",
                        TJCTextDisplayEntry, NULL,
                        tjc_stack, sizeof(tjc_stack),
                        RT_THREAD_PRIORITY_TJC, 5);
    rt_thread_startup(&tjc_thread);
    if (ret != RT_EOK)
    {
        rt_kprintf("init TJC thread failed.\n");
        return -1;
    }
    return ret;
}
INIT_APP_EXPORT(TJCScreenResourceInit);
